package org.sundatagroup.aurora.monitor.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.WebSocketSession;
import org.sundatagroup.aurora.monitor.controller.MonitorWebSocketController;
import org.sundatagroup.aurora.monitor.entity.command.SwitchProjectCommand;
import org.sundatagroup.aurora.show.entity.status.DisplayStatus;
import org.sundatagroup.aurora.show.entity.status.IStatusEntity;
import org.sundatagroup.aurora.show.service.ScreenStatusService;

import com.google.gson.JsonObject;

/**
 * <p>监控服务
 * <p>该服务管理展示屏状态和监控区前端的连接（监控区内）
 * </p>
 * 
 * @author Zdream
 * @date 2018-05-28
 * @since 0.2.0
 */
@Service
public class MonitorService {

	private final static Logger LOGGER = LoggerFactory.getLogger(MonitorService.class);

    @Autowired
	MonitorWebSocketController sender; // 反调用 控制器层

    @Autowired
	MonitorBatches monitors;

    @Autowired
    PlayListService plsv;
    
    @Autowired
	ScreenBatches screens;

    @Autowired
    ScreenStatusService sssv; // 展示区
	
	/* **********
	 * 监控前端 *
	 ********** */
	
	/**
	 * 注册监控区前端
	 * @param session
	 */
	public void registerMonitor(WebSocketSession session) {
		monitors.register(session);
	}
	
	/**
	 * 删除监控区前端
	 * @param session
	 */
	public void removeMonitor(WebSocketSession session) {
		monitors.remove(session);
	}
	
	/**
	 * 向所有监控区前端发送数据
	 * @param jo
	 *   数据内容
	 */
	public void publishToMonitors(JsonObject jo) {
		monitors.publishMessage(jo);
	}
	
	/* **********
	 *  展示屏  *
	 ********** */
	
	/**
	 * 添加展示屏
	 * @param sid
	 */
	public void addScreen(String sid) {
		IStatusEntity status = sssv.query(sid);
		screens.addScreen(status);
		sender.pushScreenCreate(screens.transform(sid));
	}
	
	/**
	 * 删除展示屏
	 * @param sid
	 */
	public void removeScreen(String sid) {
		screens.removeScreen(sid);
		sender.pushScreenDestroy(sid);
	}
	
	/**
	 * 更新展示屏的展示状态
	 * @param sid
	 *   展示屏 id
	 */
	public void updateScreenStatus(String sid) {
		IStatusEntity status = sssv.query(sid);
		screens.updateStatus(sid, status, sssv.isConnect(sid));
		pushStatusToMonitors(sid);
		
		// 暂时这样处理: 跳转至下一个需要播放的工程
		if (status.getStatus() == DisplayStatus.WAITING && screens.getPlayerParam(sid).isPlaying()) {
			playNextProject(sid);
		}
	}
	
	/**
	 * <p>更新展示屏的播放列表状态
	 * <p>如果展示屏处于等待状态, 准备播放该播放列表
	 * </p>
	 * @param sid
	 *   展示屏 id
	 * @param lid
	 *   指定的播放列表 id
	 */
	public void updateScreenPlayList(String sid, int lid) {
		plsv.assignPlayList(sid, lid);
		pushStatusToMonitors(sid);
		screens.getPlayerParam(sid).setPlaying(true);
		
		// 暂时这样处理: 跳转至下一个需要播放的工程
		if (screens.queryStatus(sid).getStatus() == DisplayStatus.WAITING) {
			playNextProject(sid);
		}
	}
	
	/**
	 * 将展示屏状态和播放列表状态发布给监控区前端
	 */
	private void pushStatusToMonitors(String sid) {
		sender.pushStatus(sid, screens.transform(sid));
	}
	
	/**
	 * 跳转至下一个需要播放的工程, 进行播放
	 * @param sid
	 */
	private void playNextProject(String sid) {
		SwitchProjectCommand command = plsv.playNext(sid);
    	
    	// 向展示前端发送
    	LOGGER.info("监控区计算出屏幕 #" + sid + " 需要播放工程 " + command.pid);
    	sssv.pushMessage(sid, command.toJson());
	}
}
